#include <stdio.h>
#include <limits.h>

/* short 短整型 占用2字节
 * 算数运算中的数据类型自动转换规则:
 * 1.算术表达式中若不存在浮点类型数，则先把短类型转为长类型，转换后最短要为int类型，举例：
 *   short + short，转为 int + int
 *   char + short，转为 int + int
 *   char + int，转为 int + int
 *   int + unsigned，转为 unsigned + unsigned
 *   short + unsigned，转为 unsigned + unsigned
 *   short + long，转为 long + long
 * */

int main() {
    short i = 2;
    printf("sizeof short: %d\n", sizeof(short)); // 2

    // short + short，转为 int + int
    short a = 0x7fff;
    short b = 0x3;
    short c = (short)(a + b);
    printf("%d\n", sizeof(a + b)); // 4
    printf("%d\n", (short)(a + b)); // -32766 a和b相加结果转为short类型后，能看出来溢出了
    printf("%d\n", sizeof(c)); // 2

    // char + short，转为 int + int
    char d = 'a';
    short e = 102;
    printf("a:%d\n", d); // 97
    printf("%d\n", sizeof(d + e)); // 4
    printf("%d\n", d + e); // 199

    // char + int，转为 int + int
    char f = 'b'; // 98
    int g = 100;
    printf("%d\n", sizeof(f + g)); // 4
    printf("%d\n", f + g); // 198

    // int + unsigned，转为 unsigned + unsigned
    // int和unsigned比较时，int按照unsigned解释后再比较
    int h = -130;
    unsigned j = 20;
    printf("%u\n", h); // -130 转为unsigned：4294967166
    printf("%u\n", h + j); // 4294967186
    if(h > j) printf("%d\n", h > j); // 1，说明 h > j 为真

    // short + unsigned，转为 unsigned + unsigned
    short m = -300;
    unsigned n = 10;
    printf("%u\n", m); // short -300 转为 unsigned: 4294966996
    printf("%u\n", m + n); // 4294967006
    if(m > n) printf("%d\n", m > n); // 1

    // short + long，转为 long + long
    short p = -8; // short转为long，正数则高位都补0，负数则高位都补1
    long q = 10;
    printf("%d\n", sizeof(p + q)); // 4
    printf("%d\n", p + q); // 2

    /*
     * 注意以下几点：1、长度比较长的类型转换成比较短的类型时，一般是将高位截去，剩下低位给长度短的类型。

             2、整型数据转换成浮点型数据时，相当于在整形数后加小数点和若干0.

             3、浮点型数据转换成整型数据时，相当于把小数部分去掉。

             4、长度短的整形转换成长度长的整形时，根据被转换类型是有符号还是无符号数，高位补足规则是不一样的。
             无符号数补足高位时，高位全补0.有符号数补足高位时，根据当前的符号位补足（即当前符号位是1，则高位全补1，反之亦同）。
             这跟逻辑右移和算术右移时高位的补齐规则有点相似。

              5、一般较低类型向较高类型转换时，计算机内部存储形式会有变化，但数值大小没有变化。
              而从较高级类型转换成较低级类型时，会有数据丢失。

             6、double类型转换成float类型时，需要通过截尾来实现，结尾之间要进行四舍五入操作。

              7、将unsigned类型转换成同样长度的有符号整形数时，数据的计算机内表示形式不变，
              数值根据不同类型对二进制码的解读规则不同而不同。（有符号数转换成相同长度的unsigned型数据时同理）

     * */

    /* 短类型转为长类型时，高位补齐规则：
     * 1.有符号数，高位按符号位补齐，即，正数全补0，负数全补1，其他的短类型转长类型也如此
     * 2.无符号数，高位都补0
     * */
    short r = -7;
    int s = (int)r; // short转int，高位需要补齐
    printf("short -7:%x\n", r); // fffffff9
    printf("short -7 to int:%x\n", s); // fffffff9
    short u = 7;
    int v = (int)u;
    printf("short 7:%x\n", u); // 00000007
    printf("short 7 to int:%x\n", v); // 00000007

    unsigned short r2 = 0x8000;
    int s2 = (int)r2;
    printf("%x\n", s2); // 8000

    /* 长类型转短类型时，不分正负，直接截断，取低位
     *
     * */
    int x = 0x1ffff111;
    short y = (short)x; // 直接截断取低位 f111
    printf("%x\n", y); // fffff111，注为什么不是f111，因为printf函数解析%x时，将参数y先转为int类型
    printf("%d\n", y); // -3823




    return 0;
}
